import Dictionary from "../dictionary";
import type { IGraph } from "../types";

class Graph<T> implements IGraph<T> {
  isDirected: boolean;
  vertices: T[];
  adjList: Dictionary<T, T[]>;

  constructor(isDirected = false) {
    this.isDirected = isDirected;
    this.adjList = new Dictionary<T, T[]>();
    this.vertices = [];
  }

  addVertex(v: T): void {
    if (this.vertices.indexOf(v) === -1) {
      this.vertices.push(v);
      this.adjList.set(v, []);
    }
  }

  addEdge(v: T, w: T): void {
    if (!this.adjList.get(v)) {
      this.addVertex(v);
    }
    if (!this.adjList.get(w)) {
      this.addVertex(w);
    }
    if (this.adjList.get(v)?.value.indexOf(w) === -1) {
      this.adjList.get(v)?.value.push(w);
    }
    if (!this.isDirected) {
      if (this.adjList.get(w)?.value.indexOf(v) === -1) {
        this.adjList.get(w)?.value.push(v);
      }
    }
  }

  getVertices(): T[] {
    return this.vertices;
  }
  getAdjacencyList(): Dictionary<T, T[]> {
    return this.adjList;
  }

  toString(): string {
    let str = "";
    for (let i = 0; i < this.vertices.length; i++) {
      str += this.vertices[i] + "-->";
      str += this.adjList.get(this.vertices[i])?.toString() || "";
      str += "\n";
    }
    return str;
  }
}

export default Graph;
